<!doctype html>



  


<html class="theme-next pisces use-motion">
<head>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-PBHRK7');</script>
<!-- End Google Tag Manager -->
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />












  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.4.0" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.0.2" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="前端 知识 面试," />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.0.2" />






<meta name="description" content="1.关于Cookie IE6或更低版本最多20个cookie IE7和之后的版本最后可以有50个cookie。 Firefox最多50个cookie chrome和Safari没有做硬性限制  优点：极高的扩展性和可用性  通过良好的编程，控制保存在cookie中的session对象的大小 通过加密和安全传输技术（SSL），减少cookie被破解的可能性 只在cookie中存放不敏感数据，即使被盗">
<meta name="keywords" content="前端 知识 面试">
<meta property="og:type" content="article">
<meta property="og:title" content="前端面试题《第一篇》浏览器常规存储">
<meta property="og:url" content="http://wurh.github.io/2019/03/29/20190329/index.html">
<meta property="og:site_name" content="华Ing&#39;s blog">
<meta property="og:description" content="1.关于Cookie IE6或更低版本最多20个cookie IE7和之后的版本最后可以有50个cookie。 Firefox最多50个cookie chrome和Safari没有做硬性限制  优点：极高的扩展性和可用性  通过良好的编程，控制保存在cookie中的session对象的大小 通过加密和安全传输技术（SSL），减少cookie被破解的可能性 只在cookie中存放不敏感数据，即使被盗">
<meta property="og:locale" content="en">
<meta property="og:updated_time" content="2019-07-12T06:10:38.186Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="前端面试题《第一篇》浏览器常规存储">
<meta name="twitter:description" content="1.关于Cookie IE6或更低版本最多20个cookie IE7和之后的版本最后可以有50个cookie。 Firefox最多50个cookie chrome和Safari没有做硬性限制  优点：极高的扩展性和可用性  通过良好的编程，控制保存在cookie中的session对象的大小 通过加密和安全传输技术（SSL），减少cookie被破解的可能性 只在cookie中存放不敏感数据，即使被盗">



<script type="text/javascript" id="hexo.configuration">
  var NexT = window.NexT || {};
  var CONFIG = {
    scheme: 'Pisces',
    sidebar: {"position":"left","display":"post"},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: 'Author'
    }
  };
</script>




  <link rel="canonical" href="http://wurh.github.io/2019/03/29/20190329/"/>


  <title> 前端面试题《第一篇》浏览器常规存储 | 华Ing's blog </title>
</head>

<body itemscope itemtype="//schema.org/WebPage" lang="en">
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-PBHRK7"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

  










  
  
    
  

<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-69412379-1', 'auto');
  ga('send', 'pageview');

</script>

  <script>
  var _hmt = _hmt || [];
  (function() {
    var hm = document.createElement("script");
    hm.src = "https://hm.baidu.com/hm.js?b3ddfb8655d8b77429e04c7a4d5bcbc1";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
  })();
  </script>


  <div class="container one-collumn sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="//schema.org/WPHeader">
      <div class="header-inner"><div class="site-meta ">
  

  <div class="custom-logo-site-title">
    <a href="/"  class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <span class="site-title">华Ing's blog</span>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>
  <p class="site-subtitle">harder and harder</p>
</div>

<div class="site-nav-toggle">
  <button>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
  </button>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories" rel="section">
            
            Categories
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
            Archives
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags" rel="section">
            
            Tags
          </a>
        </li>
      

      
    </ul>
  

  
</nav>

 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  
  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="//schema.org/Article">

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                前端面试题《第一篇》浏览器常规存储
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            <span class="post-meta-item-icon">
              <i class="fa fa-calendar-o"></i>
            </span>
            <span class="post-meta-item-text">Posted on</span>
            <time itemprop="dateCreated" datetime="2019-03-29T07:20:00+08:00" content="2019-03-29">
              2019-03-29
            </time>
          </span>

          
            <span class="post-category" >
              &nbsp; | &nbsp;
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">In</span>
              
                <span itemprop="about" itemscope itemtype="https://schema.org/Thing">
                  <a href="/categories/前端面试/" itemprop="url" rel="index">
                    <span itemprop="name">前端面试</span>
                  </a>
                </span>

                
                

              
            </span>
          

          
            
              <span class="post-comments-count">
                &nbsp; | &nbsp;
                <a href="/2019/03/29/20190329/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count ds-thread-count" data-thread-key="2019/03/29/20190329/" itemprop="commentsCount"></span>
                </a>
              </span>
            
          

          

          
          

          
        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <h4 id="1-关于Cookie"><a href="#1-关于Cookie" class="headerlink" title="1.关于Cookie"></a>1.关于Cookie</h4><ul>
<li>IE6或更低版本最多20个cookie</li>
<li>IE7和之后的版本最后可以有50个cookie。</li>
<li>Firefox最多50个cookie</li>
<li>chrome和Safari没有做硬性限制</li>
</ul>
<p>优点：极高的扩展性和可用性</p>
<ul>
<li>通过良好的编程，控制保存在cookie中的session对象的大小</li>
<li>通过加密和安全传输技术（SSL），减少cookie被破解的可能性</li>
<li>只在cookie中存放不敏感数据，即使被盗也不会有重大损失</li>
<li>控制cookie的生命期，使之不会永远有效。偷盗者很可能拿到一个过期的cookie。</li>
</ul>
<p>缺点：</p>
<ul>
<li><code>Cookie</code>数量和长度的限制。每个domain最多只能有20条cookie，每个cookie长度不能超过4KB，否则会被截掉。</li>
<li>安全性问题。如果cookie被人拦截了，那人就可以取得所有的session信息。即使加密也与事无补，因为拦截者并不需要知道cookie的意义，他只要原样转发cookie就可以达到目的了。</li>
<li>有些状态不可能保存在客户端。例如，为了防止重复提交表单，我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端，那么它起不到任何作用</li>
</ul>
<p>跨域问题：</p>
<ul>
<li>Cookie 通过domain 可以设置域的访问，目前是满足同源策略，子域名可以访问父级域名的Cookie，二 自己域名的Cookie 父级域名以及其他域名是不可访问</li>
</ul>
<p>参数解释：</p>
<ul>
<li><p>expires =》定义cookie的有效时间，值可以是一个数字（从创建cookie时算起，以天为单位）或一个Date 对象。如果省略，那么创建的cookie是会话cookie，将在用户退出浏览器时被删除。</p>
</li>
<li><p>path =》‘/’ 默认情况：只有设置cookie的网页才能读取该cookie。 定义cookie的有效路径。默认情况下， 该参数的值为创建 cookie 的网页所在路径（标准浏览器的行为）。如果你想在整个网站中访问这个cookie需要这样设置有效路径：path: ‘/’。如果你想删除一个定义了有效路径的 cookie，你需要在调用函数时包含这个路径:$.cookie(‘the_cookie’, null,<br>{ path: ‘/’ });</p>
</li>
<li><p>domain =》 默认值：创建 cookie的网页所拥有的域名。</p>
</li>
<li><p>secure =》 默认值：false。如果为true，cookie的传输需要使用安全协议（HTTPS）。</p>
</li>
<li><p>raw =》默认值：false。<br>默认情况下，读取和写入 cookie 的时候自动进行编码和解码（使用encodeURIComponent 编码， decodeURIComponent 解码）。要关闭这个功能设置 raw: true 即可。</p>
</li>
</ul>
<h4 id="2-浏览器本地存储"><a href="#2-浏览器本地存储" class="headerlink" title="2.浏览器本地存储"></a>2.浏览器本地存储</h4><p>HTML5 提供了四种在客户端存储数据的新方法，即 localStorage 、sessionStorage、globalStorage、Web Sql Database。</p>
<h5 id="localStorage"><a href="#localStorage" class="headerlink" title="localStorage"></a>localStorage</h5><p>localStorage 没有时间限制的数据存储，第二天、第二周或下一年之后，数据依然可用。也就是说，localStorage是永远不会过期的，除非主动删除数据。数据可跨越多个窗口，无视当前会话，被共同访问、使用。有点像AspNet 应用程序中的全局变量Application。</p>
<h5 id="sessionStorage"><a href="#sessionStorage" class="headerlink" title="sessionStorage"></a>sessionStorage</h5><p>顾名思义它就如同AspNet中的Session。 针对一个 session 的数据存储，任何一个页面存储的信息在窗口中同一网站的任何页面都可以访问它存储的数据。每个窗口的值都是独立的，它的数据会因窗口的关闭而丢失，不同窗口间的sessionStorage是不可以共享的。</p>
<p>localStorage /sessionStorage都有相同的Api 如</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">localStorage.length <span class="comment">//获得storage中的个数</span></span><br><span class="line">localStorage .key(n) <span class="comment">//获得storage中第n个键值对的键</span></span><br><span class="line">localStorage.key = <span class="comment">//value</span></span><br><span class="line">localStorage.setItem(key, value) <span class="comment">//添加</span></span><br><span class="line">localStorage.getItem(key) <span class="comment">//获取</span></span><br><span class="line">localStorage.removeItem(key) <span class="comment">//移除</span></span><br><span class="line">localStorage.clear() <span class="comment">//清除</span></span><br></pre></td></tr></table></figure>
<p>从上面的Api可以看出，他们其实就是键/值对，就是字典，就是JSON。既然可以看作是json ，那么对他们的操作就可以有如下方式:<br>如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">localStorage.name=<span class="string">"徐明祥"</span> ;<span class="comment">//添加</span></span><br><span class="line">localStorage[<span class="string">"name"</span>]=<span class="string">"徐明祥"</span> ; <span class="comment">//添加</span></span><br><span class="line">alert(localStorage.name);<span class="comment">//获取</span></span><br><span class="line">alert(localStorage[<span class="string">"name"</span>]);<span class="comment">//获取</span></span><br></pre></td></tr></table></figure>
<h5 id="globalStorage"><a href="#globalStorage" class="headerlink" title="globalStorage"></a>globalStorage</h5><p>在浏览器关闭以后，使用globalStorage存储的信息仍能够保留下来，和sessionStorage一样，域中任何一个页面存储的信息都能被所有的页面共享。目前只有FF支持，且只支持当前域下的globalStorage存储</p>
<p>基本用法：<br>globalStorage[‘developer.mozilla.org’] —— 在developer.mozilla.org下面所有的子域都可以通过这个存储对象来进行读和写。</p>
<p>globalStorage[‘mozilla.org’] —— 在mozilla.org域名下面的所有网页都可以通过这个存储对象来进行读和写。</p>
<p>globalStorage[‘org’] —— 在.org域名下面的所有网页都可以通过这个存储对象来进行读和写。</p>
<p>globalStorage[‘’] —— 在任何域名下的任何网页都可以通过这个存储对象来进行读和写。</p>
<p>方法属性：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">setItem(key, value) <span class="comment">// —— 设置或重置 key 值。</span></span><br><span class="line"></span><br><span class="line">getItem(key) <span class="comment">// —— 获取 key 值。</span></span><br><span class="line"></span><br><span class="line">removeItem(key)<span class="comment">//  —— 删除 key 值。</span></span><br><span class="line"></span><br><span class="line">设置 key 值：<span class="built_in">window</span>.globalStorage[<span class="string">"planabc.net"</span>].key = value;</span><br><span class="line">获取 key 值：value = <span class="built_in">window</span>.globalStorage[<span class="string">"planabc.net"</span>].key;</span><br></pre></td></tr></table></figure>
<h5 id="Web-SQL-Database"><a href="#Web-SQL-Database" class="headerlink" title="Web SQL Database"></a>Web SQL Database</h5><p>Web SQL Database （目前只谷歌浏览器支持）：我把它理解成一个Html5环境下可以用Js执行CRUD的Web数据库。</p>
<p>1、openDatabase：这个方法使用现有数据库或创建新数据库创建数据库对象。</p>
<p>2、transaction：这个方法允许我们根据情况控制事务提交或回滚。</p>
<p>3、executeSql：这个方法用于执行真实的SQL查询。</p>
<h6 id="第一步：打开连接并创建数据库"><a href="#第一步：打开连接并创建数据库" class="headerlink" title="第一步：打开连接并创建数据库"></a>第一步：打开连接并创建数据库</h6><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">var</span> dataBase = openDatabase(<span class="string">"student"</span>, <span class="string">"1.0"</span>, <span class="string">"学生表"</span>, <span class="number">1024</span> * <span class="number">1024</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; &#125;);</span><br><span class="line"><span class="keyword">if</span> (!dataBase) &#123;</span><br><span class="line">    alert(<span class="string">"数据库创建失败！"</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    alert(<span class="string">"数据库创建成功！"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>解释一下openDatabase方法打开一个已经存在的数据库，如果数据库不存在，它还可以创建数据库。几个参数意义分别是：</p>
<p>1，数据库名称。<br>2，版本号 目前为1.0,不管他，写死就OK。<br>3，对数据库的描述。<br>4，设置数据的大小。<br>5，回调函数(可省略)。<br>初次调用时创建数据库，以后就是建立连接了。<br>创建的数据库就存在本地，路径如下：<br>C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\databases\http_localhost_4987 。<br>创建的是一个sqllite数据库，完全可以用sqllite developer（点击下载） 打开文件，可以看到里面的数据。</p>
<h6 id="第二步：创建数据表"><a href="#第二步：创建数据表" class="headerlink" title="第二步：创建数据表"></a>第二步：创建数据表</h6><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">this</span>.createTable=<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  dataBase.transaction( <span class="function"><span class="keyword">function</span>(<span class="params">tx</span>) </span>&#123; </span><br><span class="line">    tx.executeSql(</span><br><span class="line">        <span class="string">"create table if not exists stu (id REAL UNIQUE, name TEXT)"</span>, </span><br><span class="line">        [], </span><br><span class="line">        <span class="function"><span class="keyword">function</span>(<span class="params">tx,result</span>)</span>&#123; alert(<span class="string">'创建stu表成功'</span>); &#125;, </span><br><span class="line">        <span class="function"><span class="keyword">function</span>(<span class="params">tx, error</span>)</span>&#123; alert(<span class="string">'创建stu表失败:'</span> + error.message); </span><br><span class="line">    &#125;);</span><br><span class="line"> &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>解释一下，<br>executeSql函数有四个参数，其意义分别是：<br>1）表示查询的字符串，使用的SQL语言是SQLite 3.6.19。<br>2）插入到查询中问号所在处的字符串数据。<br>3）成功时执行的回调函数。返回两个参数：tx和执行的结果。<br>4）一个失败时执行的回调函数。返回两个参数：tx和失败的错误信息。</p>
<h6 id="第三步：执行增删改查"><a href="#第三步：执行增删改查" class="headerlink" title="第三步：执行增删改查"></a>第三步：执行增删改查</h6><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">	<span class="comment">//1）添加数据：</span></span><br><span class="line">	<span class="keyword">this</span>.insert = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">	  dataBase.transaction(<span class="function"><span class="keyword">function</span> (<span class="params">tx</span>) </span>&#123;</span><br><span class="line">	            tx.executeSql(</span><br><span class="line">	        <span class="string">"insert  into  stu (id, name) values(?, ?)"</span>,</span><br><span class="line">	        [id, <span class="string">'徐明祥'</span>],</span><br><span class="line">	        <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; alert(<span class="string">'添加数据成功'</span>); &#125;,</span><br><span class="line">	        <span class="function"><span class="keyword">function</span> (<span class="params">tx, error</span>) </span>&#123; alert(<span class="string">'添加数据失败: '</span> + error.message); </span><br><span class="line">	        &#125; );</span><br><span class="line">	    &#125;);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//2）查询数据</span></span><br><span class="line">    <span class="keyword">this</span>.query = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  dataBase.transaction(<span class="function"><span class="keyword">function</span> (<span class="params">tx</span>) </span>&#123;</span><br><span class="line">            tx.executeSql(</span><br><span class="line">        <span class="string">"select  *  from  stu"</span>, [],</span><br><span class="line">         <span class="function"><span class="keyword">function</span> (<span class="params">tx, result</span>) </span>&#123;  <span class="comment">//执行成功的回调函数</span></span><br><span class="line">             <span class="comment">//在这里对result 做你想要做的事情吧...........</span></span><br><span class="line">            &#125;,</span><br><span class="line">         <span class="function"><span class="keyword">function</span> (<span class="params">tx, error</span>) </span>&#123;</span><br><span class="line">            alert(<span class="string">'查询失败: '</span> + error.message);</span><br><span class="line">         &#125; );</span><br><span class="line">      &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>解释一下<br>上面代码中执行成功的回调函数有一参数result。<br>result：查询出来的数据集。其数据类型为 SQLResultSet ，就如同C#中的DataTable。 </p>
<p>SQLResultSet 的定义为：<br> interface  SQLResultSet {<br>             readonly  attribute  long  insertId;<br>             readonly  attribute  long  rowsAffected;<br>             readonly  attribute  SQLResultSetRowList  rows;<br>             };<br>其中最重要的属性—SQLResultSetRowList 类型的 rows 是数据集的“行” 。<br>rows 有两个属性：length、item 。<br>故，获取查询结果的某一行某一列的值 ：result.rows[i].item[fieldname]  。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//更新数据</span></span><br><span class="line"><span class="keyword">this</span>.update = <span class="function"><span class="keyword">function</span> (<span class="params">id, name</span>) </span>&#123;</span><br><span class="line">    dataBase.transaction(<span class="function"><span class="keyword">function</span> (<span class="params">tx</span>) </span>&#123;</span><br><span class="line">            tx.executeSql(</span><br><span class="line">        <span class="string">"update  stu  set  name =  ?  where  id= ?"</span>,</span><br><span class="line">        [name, id],</span><br><span class="line">         <span class="function"><span class="keyword">function</span> (<span class="params">tx, result</span>) </span>&#123;</span><br><span class="line">         &#125;,</span><br><span class="line">        <span class="function"><span class="keyword">function</span> (<span class="params">tx, error</span>) </span>&#123;</span><br><span class="line">            alert(<span class="string">'更新失败: '</span> + error.message);</span><br><span class="line">        &#125;);</span><br><span class="line">   &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//删除数据</span></span><br><span class="line"><span class="keyword">this</span>.del = <span class="function"><span class="keyword">function</span> (<span class="params">id</span>) </span>&#123;</span><br><span class="line">        dataBase.transaction(<span class="function"><span class="keyword">function</span> (<span class="params">tx</span>) </span>&#123;</span><br><span class="line">        tx.executeSql(</span><br><span class="line">    <span class="string">"delete  from  stu  where  id= ?"</span>,</span><br><span class="line">    [id],</span><br><span class="line">     <span class="function"><span class="keyword">function</span> (<span class="params">tx, result</span>) </span>&#123;</span><br><span class="line">     &#125;,</span><br><span class="line">    <span class="function"><span class="keyword">function</span> (<span class="params">tx, error</span>) </span>&#123;</span><br><span class="line">        alert(<span class="string">'删除失败: '</span> + error.message);</span><br><span class="line">    &#125;);</span><br><span class="line"> &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//删除数据表</span></span><br><span class="line"><span class="keyword">this</span>.dropTable = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">              dataBase.transaction(<span class="function"><span class="keyword">function</span> (<span class="params">tx</span>) </span>&#123;</span><br><span class="line">            tx.executeSql(<span class="string">'drop  table  stu'</span>);</span><br><span class="line">        &#125;);</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>
<h4 id="3-浏览器缓存"><a href="#3-浏览器缓存" class="headerlink" title="3.浏览器缓存"></a>3.浏览器缓存</h4><h5 id="1）-传统的HTTP浏览器缓存策略"><a href="#1）-传统的HTTP浏览器缓存策略" class="headerlink" title="1） 传统的HTTP浏览器缓存策略"></a>1） 传统的HTTP浏览器缓存策略</h5><p>在一个网页的生命周期中，开发者为了缩短用户打开页面的时间，通常会设置很多缓存。其中包括了：</p>
<ul>
<li>浏览器缓存</li>
<li>代理服务器缓存（CDN缓存）</li>
<li>服务器缓存</li>
<li>数据库缓存</li>
</ul>
<p>等各种缓存。这些缓存大多数和前端没什么关系，也不由前端开发者控制，其中和前端较为密切的是【浏览器缓存】，但它本质上也是由服务器控制的。</p>
<hr>
<ul>
<li><p>Expires头部</p>
<p>早在HTTP协议被设计的时候，协议的起草者们就想到了缓存的事情，自然也有相应的功能，那就是Expires这个头部。每当浏览器请求时，服务器可以在相应的报文中附加这个Expires，它的典型值看起来是这样的:</p>
<pre><code class="javascript">Expires: Tue, <span class="number">01</span> May <span class="number">2018</span> <span class="number">11</span>:<span class="number">37</span>:<span class="number">06</span> GMT

</code></pre>
<p> 也就是在该资源在世界协调时2018/05/01 11:37:06才过期，我的请求时间是2018/05/01 07:37:06，所以就是这个资源在4小时之后过期，4小时之内对该资源的请求都直接使用缓存，除非你用Ctrl+F5刷新。但是呢，这种控制明显是不够精细的，这是个HTTP1.0协议中规定的头部。由于我们现在都用HTTP2.0都已经来了，HTTP1.1已经全面普及了，这个方案目前已经用的不多了。</p>
<pre><code>-------------
</code></pre></li>
<li><p>Cache-Control头部</p>
<p> Expires头部只能控制过期时间，万一请求的资源在过期时间之前就更新了，那就可能会出现显示或者功能问题。为此，HTTP协议再更新到1.1版本的时候，增加了一个新的头部Cache-Control并规定：如果同时存在Cache-Control和Expires则前者有效。它有以下常用的值可选：public private max-age s-maxage no-cache no-store等。一个典型的值看起来是以下这样：</p>
<pre><code class="javascript">Cache-Control: s-maxage=<span class="number">300</span>, public, max-age=<span class="number">60</span>  
</code></pre>
<p> 浏览器请求资源的步骤：</p>
<ul>
<li><p>步骤1：判断请求是否命中缓存，如命中则执行步骤2；如没有则执行步骤3</p>
<ul>
<li><p>步骤2：判断缓存是否过期，如没有则直接返回；如过期则执行步骤3，并带上缓存信息；</p>
</li>
<li><p>步骤3：浏览器向服务器请求资源；</p>
</li>
<li><p>步骤4：服务器判断缓存信息，如资源尚未更新，则返回304，如没有缓存信息或则资源已更新则返回200，并把资源返回。</p>
</li>
<li><p>步骤5：浏览器根据响应头部决定要不要存储缓存（只有no-store时不存储缓存信息）。</p>
</li>
</ul>
<hr>
<ul>
<li><p>【s-maxage】表示共享缓存的时间，单位是s，也就是5分钟；</p>
</li>
<li><p>【public】表示这是个共享缓存，可以被其他session使用；</p>
</li>
<li><p>【max-age】意义与s-maxage差不多，只是它用于private的情形；</p>
</li>
<li><p>【no-cache】这种策略下，浏览器会跳过步骤2，并带上缓存信息向服务器发起请求。</p>
</li>
<li><p>【no-store】这种策略下，浏览器会跳过步骤5，由于没有缓存信息，每次浏览器请求时    都不会带上缓存信息，就像第一次请求一样（Ctrl+F5效果）。</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>Last-Modified/If-Modified-Since</p>
<p>  上面说了，浏览器在有缓存信息的情况下，会带上缓存信息发起请求，那这个信息是怎么来的？又是怎么带在Request的头部当中呢？<br>原来，服务器在响应请求时，除了返回【Cache-Control】头部外，还会返回一个【Last-Modified】头部，用于指定该资源的服务器更新时间。当该资源在浏览器端过期时（由max-age或者no-cache决定），浏览器会带上缓存信息去发起请求，这个信息就由Request中的【If-Modified-Since】指定，通常也就是上次Response中【Last-Modified】的值。典型值如下：</p>
</li>
</ul>
<pre><code class="javascript">  <span class="comment">//Response:</span>
Last-Modified: Sat, <span class="number">01</span> Jan <span class="number">2000</span> <span class="number">00</span>:<span class="number">00</span>:<span class="number">00</span> GMT
<span class="comment">//Request:</span>
If-Modified-Since: Sat, <span class="number">01</span> Jan <span class="number">2000</span> <span class="number">00</span>:<span class="number">00</span>:<span class="number">00</span> GMT 
</code></pre>
<ul>
<li><p>Etag/If-None-Match</p>
<p>  【Last-Modified/If-Modified-Since】提供的控制已经比较多了，但有些时候，开发者还是不满意，因为它们只能提供对资源时间的控制，并只有精确到秒级。如果有些资源变化非常快，或者有些资源定时生成，但内容却是一样的，这些情况下【Last-Modified/If-Modified-Since】就不是很适用。</p>
<p> 为此，HTTP1.1规定了【Etag/If-None-Match】这两个头部，它们的用法和【Last-Modified/If-Modified-Since】完全相同，一个用于响应，一个用于请求。只不过Etag用的不是时间，而是服务器规定的一个标签（通常是资源内容、大小、时间的hash值）。这样服务器通过这个头部可以更加啊精确地控制资源的缓存策略。<br>同样的，由于这个头部控制更加精细， 所以它的优先级会高于【Last-Modified/If-Modified-Since】,就像【Cache-Control】高于【Expires】一样。</p>
</li>
</ul>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        
  <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
    <div>坚持原创技术分享，您的支持将鼓励我继续创作！</div>
    <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
      <span>赏</span>
    </button>
    <div id="QR" style="display: none;">
      
        <div id="wechat" style="display: inline-block">
          <img id="wechat_qr" src="https://wurh.github.io/images/others/weixinshou.png" alt="华Ing WeChat Pay"/>
          <p>微信打赏</p>
        </div>
      
      
        <div id="alipay" style="display: inline-block">
          <img id="alipay_qr" src="https://wurh.github.io/images/others/alifu.png" alt="华Ing Alipay"/>
          <p>支付宝打赏</p>
        </div>
      
    </div>
  </div>


      
    </div>

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/前端-知识-面试/" rel="tag">#前端 知识 面试</a>
          
        </div>
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/03/28/20190328/" rel="next" title="Skywalking 部署与使用《一》">
                <i class="fa fa-chevron-left"></i> Skywalking 部署与使用《一》
              </a>
            
          </div>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/03/29/20190330/" rel="prev" title="前端面试题《第二篇》 Service workder">
                前端面试题《第二篇》 Service workder <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
        
<script>
  with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='//bdimg.share.baidu.com/static/api/js/share.js?cdnversion='+~(-new Date()/36e5)];
</script>

      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
      <div class="ds-thread" data-thread-key="2019/03/29/20190329/"
           data-title="前端面试题《第一篇》浏览器常规存储" data-url="http://wurh.github.io/2019/03/29/20190329/">
      </div>
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            Table of Contents
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            Overview
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel ">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="//schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="https://wurh.github.io/images/avatar/logo.jpg?123456"
               alt="华Ing" />
          <p class="site-author-name" itemprop="name">华Ing</p>
          <p class="site-description motion-element" itemprop="description">harder and harder</p>
        </div>
        <nav class="site-state motion-element">
          <div class="site-state-item site-state-posts">
            <a href="/archives">
              <span class="site-state-item-count">56</span>
              <span class="site-state-item-name">posts</span>
            </a>
          </div>

          
            <div class="site-state-item site-state-categories">
              <a href="/categories">
                <span class="site-state-item-count">11</span>
                <span class="site-state-item-name">categories</span>
              </a>
            </div>
          

          
            <div class="site-state-item site-state-tags">
              <a href="/tags">
                <span class="site-state-item-count">15</span>
                <span class="site-state-item-name">tags</span>
              </a>
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/wurh" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i>
                  
                  GitHub
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://weibo.com/1674582564/profile?topnav=1&wvr=6" target="_blank" title="微博">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  微博
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://www.zhihu.com/people/wu-rong-hua-56" target="_blank" title="知乎">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  知乎
                </a>
              </span>
            
          
        </div>

        
        

        
        
          <div class="links-of-blogroll motion-element links-of-blogroll-inline">
            <div class="links-of-blogroll-title">
              <i class="fa  fa-fw fa-globe"></i>
              Links
            </div>
            <ul class="links-of-blogroll-list">
              
                <li class="links-of-blogroll-item">
                  <a href="http://fsiaonma.github.io/" title="sam博客" target="_blank">sam博客</a>
                </li>
              
                <li class="links-of-blogroll-item">
                  <a href="http://shenjoel.github.io/" title="joel博客" target="_blank">joel博客</a>
                </li>
              
                <li class="links-of-blogroll-item">
                  <a href="http://firewood1122.github.io" title="firewood博客" target="_blank">firewood博客</a>
                </li>
              
                <li class="links-of-blogroll-item">
                  <a href="http://reqianduan.com" title="热前端" target="_blank">热前端</a>
                </li>
              
                <li class="links-of-blogroll-item">
                  <a href="http://opentutorial.info/" title="黄超博客" target="_blank">黄超博客</a>
                </li>
              
            </ul>
          </div>
        

      </section>

      
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">
            
              
            
            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-关于Cookie"><span class="nav-number">1.</span> <span class="nav-text">1.关于Cookie</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-浏览器本地存储"><span class="nav-number">2.</span> <span class="nav-text">2.浏览器本地存储</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#localStorage"><span class="nav-number">2.1.</span> <span class="nav-text">localStorage</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#sessionStorage"><span class="nav-number">2.2.</span> <span class="nav-text">sessionStorage</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#globalStorage"><span class="nav-number">2.3.</span> <span class="nav-text">globalStorage</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#Web-SQL-Database"><span class="nav-number">2.4.</span> <span class="nav-text">Web SQL Database</span></a><ol class="nav-child"><li class="nav-item nav-level-6"><a class="nav-link" href="#第一步：打开连接并创建数据库"><span class="nav-number">2.4.1.</span> <span class="nav-text">第一步：打开连接并创建数据库</span></a></li><li class="nav-item nav-level-6"><a class="nav-link" href="#第二步：创建数据表"><span class="nav-number">2.4.2.</span> <span class="nav-text">第二步：创建数据表</span></a></li><li class="nav-item nav-level-6"><a class="nav-link" href="#第三步：执行增删改查"><span class="nav-number">2.4.3.</span> <span class="nav-text">第三步：执行增删改查</span></a></li></ol></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-浏览器缓存"><span class="nav-number">3.</span> <span class="nav-text">3.浏览器缓存</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#1）-传统的HTTP浏览器缓存策略"><span class="nav-number">3.1.</span> <span class="nav-text">1） 传统的HTTP浏览器缓存策略</span></a></li></ol></li></ol></div>
            
          </div>
        </section>
      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy;  2013 - 
  <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">华Ing</span>
</div>

<div class="powered-by">
  Powered by <a class="theme-link" href="https://hexo.io">Hexo</a>
</div>

<div class="theme-info">
  Theme -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Pisces
  </a>
</div>

        

        
      </div>
    </footer>

    <div class="back-to-top">
      <i class="fa fa-arrow-up"></i>
    </div>
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  



  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.0.2"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.0.2"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.0.2"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.0.2"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.0.2"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.0.2"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.0.2"></script>



  

  
    
  

  <script type="text/javascript">
    var duoshuoQuery = {short_name:"wurh"};
    (function() {
      var ds = document.createElement('script');
      ds.type = 'text/javascript';ds.async = true;
      ds.id = 'duoshuo-script';
      ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
      ds.charset = 'UTF-8';
      (document.getElementsByTagName('head')[0]
      || document.getElementsByTagName('body')[0]).appendChild(ds);
    })();
  </script>

  
    
    <script src="/lib/ua-parser-js/dist/ua-parser.min.js?v=0.7.9"></script>
    <script src="/js/src/hook-duoshuo.js"></script>
  






  
  

  

  

  

  


</body>
</html>
